/*
 * EMARo VAL Editor and Parser
 * Alejandro Sanchez Sedano
 * Joao Miguel Viana da Silva Coelho
 */
package ParserApp;

import java.awt.AWTException;
import java.awt.Cursor;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.*;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.text.BadLocationException;
import javax.swing.tree.DefaultMutableTreeNode;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;

/**
 *
 * @author Alejandro Sánchez Sedano
 * @author Joao Miguel Viana da Silva Coelho
 */
public class ParserGUI extends javax.swing.JFrame implements ActionListener {
    private Preferences prefs;

    String path, content;
    Boolean is_saved = true;

    public ParserGUI() {
        initComponents();

        //Output text pane redirects console, to write use System.out.println();
        MessageConsole console = new MessageConsole(output,true);
        console.redirectOut();
        console.redirectErr();
        
        //Load last directory used preference from registry
        prefs = Preferences.userRoot().node(this.getClass().getName());
        
        //Initialize jsyntaxpane, takes control of jEditorPane 't'
        jsyntaxpane.DefaultSyntaxKit.initKit();
        t.setContentType("text/val2");
        t.setCursor(new Cursor(Cursor.TEXT_CURSOR));

        //File drop listener, takes only first file and checks extension
        FileDrop fileDrop = new FileDrop(t, new FileDrop.Listener()
                            {   public void filesDropped( java.io.File[] files )
                                    {   
                                        try
                                        {   if (files.length!=0){
                                                myfile= files[0];
                                                if(myfile.getName().endsWith(".val") || myfile.getName().endsWith(".vplus") || myfile.getName().endsWith(".txt")){
                                                BufferedReader input = new BufferedReader(new FileReader(myfile));
                                                StringBuilder str = new StringBuilder();
                                                String line;
                                                while((line = input.readLine()) != null) // st is declared as string avobe
                                                str.append(line).append("\n");
                                                t.setText(str.toString());
                                                content = t.getText();
                                                path = myfile.toString();
                                                is_saved = true;
                                                prefs.put("dirPref",path);
                                                setTitle("VAL Parser - " + myfile.getName());
                                                ((jsyntaxpane.SyntaxDocument)t.getDocument()).clearUndos();
                                                }
                                            }
                                        }
                                        catch(FileNotFoundException e)
                                        {
                                            System.err.println("file not found: \n"+e);
                                        }
                                        catch(IOException e)
                                        {
                                            System.err.println("file could not be read: \n"+e);
                                        }
                                    }
                            });
        path = "";
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPopupMenu1 = new javax.swing.JPopupMenu();
        jMClearOutput = new javax.swing.JMenuItem();
        jAbout = new javax.swing.JDialog();
        jTitle = new javax.swing.JLabel();
        jAuthorsB = new javax.swing.JLabel();
        jAuthor1 = new javax.swing.JLabel();
        jAuthor2 = new javax.swing.JLabel();
        jVersionB = new javax.swing.JLabel();
        jVersion = new javax.swing.JLabel();
        jLibrariesB = new javax.swing.JLabel();
        jANTLR = new javax.swing.JLabel();
        jJSyntaxPane = new javax.swing.JLabel();
        jLAbout = new javax.swing.JLabel();
        jFileDrop = new javax.swing.JLabel();
        jBOptim = new javax.swing.JButton();
        jToolBar = new javax.swing.JToolBar();
        jBNew = new javax.swing.JButton();
        jBOpen = new javax.swing.JButton();
        jBSave = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JToolBar.Separator();
        jBUndo = new javax.swing.JButton();
        jBRedo = new javax.swing.JButton();
        jBFind = new javax.swing.JButton();
        jBComments = new javax.swing.JButton();
        jSeparator2 = new javax.swing.JToolBar.Separator();
        jBCombo = new javax.swing.JComboBox();
        jBParse = new javax.swing.JButton();
        filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        jSeparator3 = new javax.swing.JToolBar.Separator();
        jBTree = new javax.swing.JButton();
        jTAlwaysTop = new javax.swing.JToggleButton();
        jBAbout = new javax.swing.JButton();
        jSplitPane2 = new javax.swing.JSplitPane();
        jSplitPane3 = new javax.swing.JSplitPane();
        jScrollPane2 = new javax.swing.JScrollPane();
        t = new javax.swing.JEditorPane();
        jScrollPane3 = new javax.swing.JScrollPane();
        jPanel1 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTree = new javax.swing.JTree();
        jLMSpeed = new javax.swing.JLabel();
        jSlider = new javax.swing.JSlider();
        jLSpeed = new javax.swing.JLabel();
        jCheck = new javax.swing.JCheckBox();
        jParseBtn = new javax.swing.JButton();
        jWarning = new javax.swing.JButton();
        jCIgnore = new javax.swing.JCheckBox();
        jSeparator4 = new javax.swing.JSeparator();
        jLCode = new javax.swing.JLabel();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMNew = new javax.swing.JMenuItem();
        jMOpen = new javax.swing.JMenuItem();
        jMSave = new javax.swing.JMenuItem();
        jMUndo = new javax.swing.JMenuItem();
        jMRedo = new javax.swing.JMenuItem();
        jMFind = new javax.swing.JMenuItem();
        jMParse = new javax.swing.JMenuItem();
        jMOptim = new javax.swing.JMenuItem();

        jMClearOutput.setText("Clear Output");
        jMClearOutput.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMClearOutputActionPerformed(evt);
            }
        });
        jPopupMenu1.add(jMClearOutput);

        jAbout.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        jAbout.setTitle("About");
        jAbout.setAlwaysOnTop(true);
        jAbout.setLocationByPlatform(true);
        jAbout.setMinimumSize(new java.awt.Dimension(380, 270));
        jAbout.setName("jAbout");
        jAbout.setResizable(false);
        jAbout.setType(java.awt.Window.Type.POPUP);
        jAbout.addWindowFocusListener(new java.awt.event.WindowFocusListener() {
            public void windowGainedFocus(java.awt.event.WindowEvent evt) {
            }
            public void windowLostFocus(java.awt.event.WindowEvent evt) {
                jAboutWindowLostFocus(evt);
            }
        });

        jTitle.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
        jTitle.setText("VAL Parser 2012");

        jAuthorsB.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
        jAuthorsB.setText("Authors:");

        jAuthor1.setText("Alejandro Sánchez Sedano");

        jAuthor2.setText("João Miguel Viana da Silva Coelho");

        jVersionB.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
        jVersionB.setText("Version:");

        jVersion.setText("1.3");
        jVersion.setToolTipText("");

        jLibrariesB.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
        jLibrariesB.setText("Libraries:");

        jANTLR.setText("ANTLR v3.4");

        jJSyntaxPane.setText("JSyntaxPane Release 0.9.6 custom");

        jLAbout.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/rx90.png"))); // NOI18N
        jLAbout.setText("                                                        ");
        jLAbout.setToolTipText("");
        jLAbout.setFocusable(false);
        jLAbout.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        jLAbout.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jLAboutMouseClicked(evt);
            }
        });

        jFileDrop.setText("FileDrop 1.0.1");

        javax.swing.GroupLayout jAboutLayout = new javax.swing.GroupLayout(jAbout.getContentPane());
        jAbout.getContentPane().setLayout(jAboutLayout);
        jAboutLayout.setHorizontalGroup(
            jAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jAboutLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jAboutLayout.createSequentialGroup()
                        .addGroup(jAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jVersionB)
                            .addComponent(jLibrariesB)
                            .addGroup(jAboutLayout.createSequentialGroup()
                                .addGap(10, 10, 10)
                                .addGroup(jAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jAuthor2)
                                    .addComponent(jANTLR)
                                    .addComponent(jVersion)
                                    .addComponent(jJSyntaxPane)
                                    .addComponent(jFileDrop))))
                        .addGap(0, 182, Short.MAX_VALUE))
                    .addGroup(jAboutLayout.createSequentialGroup()
                        .addGroup(jAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jAuthorsB)
                            .addGroup(jAboutLayout.createSequentialGroup()
                                .addGap(10, 10, 10)
                                .addComponent(jAuthor1))
                            .addComponent(jTitle))
                        .addContainerGap())))
            .addGroup(jAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jAboutLayout.createSequentialGroup()
                    .addGap(0, 0, Short.MAX_VALUE)
                    .addComponent(jLAbout)
                    .addGap(0, 0, Short.MAX_VALUE)))
        );
        jAboutLayout.setVerticalGroup(
            jAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jAboutLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jTitle)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jAuthorsB)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jAuthor1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jAuthor2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jVersionB)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jVersion)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLibrariesB)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jANTLR)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jJSyntaxPane)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jFileDrop)
                .addContainerGap(37, Short.MAX_VALUE))
            .addGroup(jAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jAboutLayout.createSequentialGroup()
                    .addGap(0, 0, Short.MAX_VALUE)
                    .addComponent(jLAbout)
                    .addGap(0, 0, Short.MAX_VALUE)))
        );

        jBOptim.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/HtmlBalanceBracesHS.png"))); // NOI18N
        jBOptim.setText("Optimize");
        jBOptim.setToolTipText("Force generate optimized code... (Ctrl+F5)");
        jBOptim.setFocusable(false);
        jBOptim.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        jBOptim.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);

        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
        setTitle("VAL Parser");
        setIconImages(null);
        setMinimumSize(new java.awt.Dimension(600, 480));
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        jToolBar.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));
        jToolBar.setFloatable(false);
        jToolBar.setRollover(true);
        jToolBar.setToolTipText("");
        jToolBar.setAlignmentY(0.5F);
        jToolBar.setMargin(new java.awt.Insets(0, 1, 0, 1));

        jBNew.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/NewDocumentHS.png"))); // NOI18N
        jBNew.setToolTipText("New File... (Ctrl+N)");
        jBNew.setFocusable(false);
        jBNew.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jBNew.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jBNew.addActionListener(this);
        jToolBar.add(jBNew);

        jBOpen.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/openHS.png"))); // NOI18N
        jBOpen.setToolTipText("Open File... (Ctrl+O)");
        jBOpen.setFocusable(false);
        jBOpen.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jBOpen.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jBOpen.addActionListener(this);
        jToolBar.add(jBOpen);

        jBSave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/saveHS.png"))); // NOI18N
        jBSave.setToolTipText("Save File... (Ctrl+S)");
        jBSave.setFocusable(false);
        jBSave.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jBSave.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jBSave.addActionListener(this);
        jToolBar.add(jBSave);
        jToolBar.add(jSeparator1);

        jBUndo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/Edit_UndoHS.png"))); // NOI18N
        jBUndo.setToolTipText("Undo... (Ctrl+Z)");
        jBUndo.setFocusable(false);
        jBUndo.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jBUndo.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jBUndo.addActionListener(this);
        jToolBar.add(jBUndo);

        jBRedo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/Edit_RedoHS.png"))); // NOI18N
        jBRedo.setToolTipText("Redo... (Ctrl+Y)");
        jBRedo.setFocusable(false);
        jBRedo.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jBRedo.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jBRedo.addActionListener(this);
        jToolBar.add(jBRedo);

        jBFind.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/FindHS.png"))); // NOI18N
        jBFind.setToolTipText("Find... (Ctrl+F)");
        jBFind.setFocusable(false);
        jBFind.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jBFind.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jBFind.addActionListener(this);
        jToolBar.add(jBFind);

        jBComments.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/comment.png"))); // NOI18N
        jBComments.setToolTipText("Toggle Comments... (Ctrl+R)");
        jBComments.setFocusable(false);
        jBComments.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jBComments.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jBComments.addActionListener(this);
        jToolBar.add(jBComments);
        jToolBar.add(jSeparator2);

        jBCombo.setEditable(true);
        jBCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "VAL II", "V+" }));
        jBCombo.setToolTipText("Select language...");
        jBCombo.setEnabled(false);
        jBCombo.setFocusable(false);
        jBCombo.setMaximumSize(new java.awt.Dimension(60, 20));
        jBCombo.setMinimumSize(new java.awt.Dimension(60, 20));
        jBCombo.setPreferredSize(new java.awt.Dimension(60, 20));
        jToolBar.add(jBCombo);

        jBParse.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/FormRunHS.png"))); // NOI18N
        jBParse.setText("Run");
        jBParse.setToolTipText("Run... (F5)");
        jBParse.setFocusable(false);
        jBParse.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        jBParse.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jBParse.addActionListener(this);
        jToolBar.add(jBParse);
        jToolBar.add(filler2);
        jToolBar.add(jSeparator3);

        jBTree.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/OrgChartHS.png"))); // NOI18N
        jBTree.setToolTipText("Expand Workspace");
        jBTree.setFocusable(false);
        jBTree.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jBTree.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jBTree.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBTreeActionPerformed(evt);
            }
        });
        jToolBar.add(jBTree);

        jTAlwaysTop.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/BringToFrontHS.png"))); // NOI18N
        jTAlwaysTop.setToolTipText("Always on Top");
        jTAlwaysTop.setFocusable(false);
        jTAlwaysTop.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jTAlwaysTop.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jTAlwaysTop.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jTAlwaysTopMouseClicked(evt);
            }
        });
        jToolBar.add(jTAlwaysTop);

        jBAbout.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/Help.png"))); // NOI18N
        jBAbout.setToolTipText("About...");
        jBAbout.setFocusable(false);
        jBAbout.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jBAbout.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jBAbout.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBAboutActionPerformed(evt);
            }
        });
        jToolBar.add(jBAbout);

        jSplitPane2.setBorder(null);
        jSplitPane2.setDividerLocation(390);
        jSplitPane2.setDividerSize(10);
        jSplitPane2.setResizeWeight(0.9);
        jSplitPane2.setFocusable(false);
        jSplitPane2.setPreferredSize(new java.awt.Dimension(500, 394));

        jSplitPane3.setDividerLocation(250);
        jSplitPane3.setDividerSize(8);
        jSplitPane3.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane3.setResizeWeight(0.75);
        jSplitPane3.setFocusable(false);
        jSplitPane3.setMinimumSize(new java.awt.Dimension(250, 56));

        t.setContentType("text/val2");
        t.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                tKeyReleased(evt);
            }
        });
        jScrollPane2.setViewportView(t);
        t.getAccessibleContext().setAccessibleName("");
        t.getAccessibleContext().setAccessibleDescription("text/val2");

        jSplitPane3.setLeftComponent(jScrollPane2);

        output.setEditable(false);
        output.setText("Output:");
        output.setComponentPopupMenu(jPopupMenu1);
        output.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        output.setFocusable(false);
        jScrollPane3.setViewportView(output);

        jSplitPane3.setRightComponent(jScrollPane3);

        jSplitPane2.setLeftComponent(jSplitPane3);

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(""));

        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("Workspace");
        javax.swing.tree.DefaultMutableTreeNode treeNode2 = new javax.swing.tree.DefaultMutableTreeNode("Programs");
        javax.swing.tree.DefaultMutableTreeNode treeNode3 = new javax.swing.tree.DefaultMutableTreeNode("Loaded");
        javax.swing.tree.DefaultMutableTreeNode treeNode4 = new javax.swing.tree.DefaultMutableTreeNode("(Empty)");
        treeNode3.add(treeNode4);
        treeNode2.add(treeNode3);
        treeNode1.add(treeNode2);
        treeNode2 = new javax.swing.tree.DefaultMutableTreeNode("Variables");
        treeNode3 = new javax.swing.tree.DefaultMutableTreeNode("(Empty)");
        treeNode2.add(treeNode3);
        treeNode1.add(treeNode2);
        treeNode2 = new javax.swing.tree.DefaultMutableTreeNode("Locations");
        treeNode3 = new javax.swing.tree.DefaultMutableTreeNode("(Empty)");
        treeNode2.add(treeNode3);
        treeNode1.add(treeNode2);
        jTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        jScrollPane1.setViewportView(jTree);

        jLMSpeed.setText("Monitor speed:");

        jSlider.setFont(new java.awt.Font("Tahoma", 0, 8)); // NOI18N
        jSlider.setMajorTickSpacing(25);
        jSlider.setMinorTickSpacing(5);
        jSlider.setPaintTicks(true);
        jSlider.setSnapToTicks(true);
        jSlider.setToolTipText("Set the monitor speed");
        jSlider.setValue(30);
        jSlider.setFocusable(false);
        jSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSliderStateChanged(evt);
            }
        });

        jLSpeed.setText("30%");

        jCheck.setSelected(true);
        jCheck.setText("Clear memory");
        jCheck.setToolTipText("Empties the robot memory");
        jCheck.setFocusable(false);
        jCheck.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        jCheck.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jCheck.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jCheckActionPerformed(evt);
            }
        });

        jParseBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/FormRunHS.png"))); // NOI18N
        jParseBtn.setText("Run");
        jParseBtn.setToolTipText("Run... (F5)");
        jParseBtn.setFocusable(false);
        jParseBtn.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        jParseBtn.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);

        jWarning.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Resources/WarningHS.png"))); // NOI18N
        jWarning.setText(" ");
        jWarning.setToolTipText("");
        jWarning.setBorder(null);
        jWarning.setBorderPainted(false);
        jWarning.setContentAreaFilled(false);
        jWarning.setEnabled(false);
        jWarning.setFocusPainted(false);
        jWarning.setFocusable(false);
        jWarning.setHideActionText(true);
        jWarning.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jWarning.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);

        jCIgnore.setText("Ignore errors");
        jCIgnore.setToolTipText("Ignore errors and generate output");
        jCIgnore.setFocusable(false);
        jCIgnore.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);

        jParseBtn.addActionListener(this);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jSeparator4)
                    .addComponent(jParseBtn, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jSlider, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
                        .addComponent(jCheck)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 42, Short.MAX_VALUE)
                        .addComponent(jWarning))
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
                        .addComponent(jCIgnore)
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
                        .addComponent(jLMSpeed)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jLSpeed)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 203, Short.MAX_VALUE)
                .addGap(23, 23, 23)
                .addComponent(jSeparator4, javax.swing.GroupLayout.PREFERRED_SIZE, 9, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLMSpeed)
                    .addComponent(jLSpeed))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jCIgnore)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jCheck)
                    .addComponent(jWarning, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jParseBtn, javax.swing.GroupLayout.PREFERRED_SIZE, 34, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        jSplitPane2.setRightComponent(jPanel1);

        jLCode.setText("Code:");

        jMenuBar1.setPreferredSize(new java.awt.Dimension(0, 0));

        jMenu1.setText("File");

        jMNew.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.CTRL_MASK));
        jMNew.setText("New");
        jMNew.setToolTipText("");
        jMNew.addActionListener(this);
        jMenu1.add(jMNew);

        jMOpen.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        jMOpen.setText("Open");
        jMOpen.setToolTipText("");
        jMOpen.addActionListener(this);
        jMenu1.add(jMOpen);

        jMSave.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
        jMSave.setText("Save");
        jMSave.setToolTipText("");
        jMSave.addActionListener(this);
        jMenu1.add(jMSave);

        jMUndo.setText("Undo");
        jMUndo.setToolTipText("");
        jMenu1.add(jMUndo);

        jMRedo.setText("Redo");
        jMRedo.setToolTipText("");
        jMenu1.add(jMRedo);

        jMFind.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F, java.awt.event.InputEvent.CTRL_MASK));
        jMFind.setText("Find");
        jMFind.setToolTipText("");
        jMFind.addActionListener(this);
        jMenu1.add(jMFind);

        jMParse.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F5, 0));
        jMParse.setText("Parse");
        jMParse.setToolTipText("");
        jMParse.addActionListener(this);
        jMenu1.add(jMParse);

        jMOptim.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F5, java.awt.event.InputEvent.CTRL_MASK));
        jMOptim.setText("Optimize");
        jMOptim.setToolTipText("");
        jMOptim.addActionListener(this);
        jMenu1.add(jMOptim);

        jMenuBar1.add(jMenu1);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jToolBar, javax.swing.GroupLayout.DEFAULT_SIZE, 600, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jSplitPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLCode)
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jToolBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLCode)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 398, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    
    /**
     * The functions below are generated via the design module, they are event
     * based for each widget, names are self explanatory.
     */

    private void jSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSliderStateChanged
        jLSpeed.setText(jSlider.getValue()+"%");
        check_warning();
    }//GEN-LAST:event_jSliderStateChanged

    private void jTAlwaysTopMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTAlwaysTopMouseClicked
        this.setAlwaysOnTop(!(this.isAlwaysOnTop()));

    }//GEN-LAST:event_jTAlwaysTopMouseClicked
    private void jBTreeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jBTreeActionPerformed
        if (jTree.isCollapsed(1)){
            for (int i = 0; i < jTree.getRowCount(); i++) {
                jTree.expandRow(i);
            }
        } else {
            for (int i = jTree.getRowCount()-1; i > 0; i--) {
                jTree.collapseRow(i);
            }
        }
    }//GEN-LAST:event_jBTreeActionPerformed

    private void jMClearOutputActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMClearOutputActionPerformed
        output.setText("Output:");
    }//GEN-LAST:event_jMClearOutputActionPerformed

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        file_exit();
    }//GEN-LAST:event_formWindowClosing

    //tKeyReleased is to detect changes in the file and add the * in the title.
    private void tKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_tKeyReleased
            if (is_saved & !t.getText().equals(content)){
            is_saved = false;
            setTitle(this.getTitle()+" *");           
        }
    }//GEN-LAST:event_tKeyReleased

    private void jCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckActionPerformed
        check_warning();
    }//GEN-LAST:event_jCheckActionPerformed

    private void jBAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jBAboutActionPerformed
        help_about();
    }//GEN-LAST:event_jBAboutActionPerformed

    private void jAboutWindowLostFocus(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_jAboutWindowLostFocus
        jAbout.dispose();
    }//GEN-LAST:event_jAboutWindowLostFocus

    private void jLAboutMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLAboutMouseClicked
        jAbout.dispose();
//                for (int i = 0; i < 23; i++) {
//                    try {
//                        jAbout.setLocation((int)(Math.random()*1280), (int)(Math.random()*1024));
//                        Thread.sleep(100);
//                    } catch (InterruptedException ex) {
//                        Logger.getLogger(ParserGUI.class.getName()).log(Level.SEVERE, null, ex);
//                    }
//                }
    }//GEN-LAST:event_jLAboutMouseClicked

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    //-->NO-->javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    //UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
                    //UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                    //UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
                    //UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(ParserGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(ParserGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(ParserGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(ParserGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
      //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ParserGUI().setVisible(true);

            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.Box.Filler filler2;
    private javax.swing.JLabel jANTLR;
    private javax.swing.JDialog jAbout;
    private javax.swing.JLabel jAuthor1;
    private javax.swing.JLabel jAuthor2;
    private javax.swing.JLabel jAuthorsB;
    private javax.swing.JButton jBAbout;
    private javax.swing.JComboBox jBCombo;
    private javax.swing.JButton jBComments;
    private javax.swing.JButton jBFind;
    private javax.swing.JButton jBNew;
    private javax.swing.JButton jBOpen;
    private javax.swing.JButton jBOptim;
    private javax.swing.JButton jBParse;
    private javax.swing.JButton jBRedo;
    private javax.swing.JButton jBSave;
    private javax.swing.JButton jBTree;
    private javax.swing.JButton jBUndo;
    private javax.swing.JCheckBox jCIgnore;
    private javax.swing.JCheckBox jCheck;
    private javax.swing.JLabel jFileDrop;
    private javax.swing.JLabel jJSyntaxPane;
    private javax.swing.JLabel jLAbout;
    private javax.swing.JLabel jLCode;
    private javax.swing.JLabel jLMSpeed;
    private javax.swing.JLabel jLSpeed;
    private javax.swing.JLabel jLibrariesB;
    private javax.swing.JMenuItem jMClearOutput;
    private javax.swing.JMenuItem jMFind;
    private javax.swing.JMenuItem jMNew;
    private javax.swing.JMenuItem jMOpen;
    private javax.swing.JMenuItem jMOptim;
    private javax.swing.JMenuItem jMParse;
    private javax.swing.JMenuItem jMRedo;
    private javax.swing.JMenuItem jMSave;
    private javax.swing.JMenuItem jMUndo;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JButton jParseBtn;
    private javax.swing.JPopupMenu jPopupMenu1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JToolBar.Separator jSeparator1;
    private javax.swing.JToolBar.Separator jSeparator2;
    private javax.swing.JToolBar.Separator jSeparator3;
    private javax.swing.JSeparator jSeparator4;
    private javax.swing.JSlider jSlider;
    private javax.swing.JSplitPane jSplitPane2;
    private javax.swing.JSplitPane jSplitPane3;
    private javax.swing.JToggleButton jTAlwaysTop;
    private javax.swing.JLabel jTitle;
    private javax.swing.JToolBar jToolBar;
    private javax.swing.JTree jTree;
    private javax.swing.JLabel jVersion;
    private javax.swing.JLabel jVersionB;
    private javax.swing.JButton jWarning;
    private final javax.swing.JTextPane output = new javax.swing.JTextPane();
    public javax.swing.JEditorPane t;
    // End of variables declaration//GEN-END:variables
    public static File myfile;


/**
 * Input handler, relates listener to buttons with same function.
 * To modify listeners for controls go to 'Code' in 'Properties' of the swing 
 * Design editor on the desired swing component.
 */
    @Override
public void actionPerformed(ActionEvent e){
        if(e.getSource()==jBNew || e.getSource()==jMNew)
            file_new();
        else if(e.getSource()==jBOpen || e.getSource()==jMOpen)
            file_open();
        else if(e.getSource()==jBSave || e.getSource()==jMSave)
            file_save();
        else if (e.getSource()==jBOptim || e.getSource()==jMOptim){
            try {
                file_save();
                if (is_saved){
                System.out.println("warning: ignoring errors");
                optimize_code();
                }
            } catch (IOException ex) {
                Logger.getLogger(ParserGUI.class.getName()).log(Level.SEVERE, null, ex);
            }
            }
        else if(e.getSource()==jBParse || e.getSource()==jMParse || e.getSource()==jParseBtn)
            try {
            run_parser();
            } catch (BadLocationException ex) {
                Logger.getLogger(ParserGUI.class.getName()).log(Level.SEVERE, null, ex);
            }
        else if(e.getSource()==jBUndo)
            edit_undo();
        else if(e.getSource()==jBRedo)
            edit_redo();
        else if(e.getSource()==jBComments)
            edit_toggle_comments();
        else if(e.getSource()==jBFind || e.getSource()==jMFind)
              edit_find();
    }


/**
 * Start declaration of actions (functions).
 * Some important variables:
 *  content -> stores the value of the code immediately after saving.
 *  path -> variable that contains the directory preference.
 *  is_saved -> boolean to check if file is saved.
 *  t -> jEditorPane, where the code is shown.
 *  output -> Read only jEditorPane, where the errors and information is shown.
 */

    public void file_new(){
        if(t.getText().equals("") || t.getText().equals(content))
        {
            t.setText("");
            content = "";
            path = "";
            setTitle("VAL Parser - untitled");
            is_saved = true;
            empty_tree();
            output.setText("Output:");
            ((jsyntaxpane.SyntaxDocument)t.getDocument()).clearUndos();
        }
        else
        {
            int a = JOptionPane.showConfirmDialog(this, "The text has been changed\nDo you want to save the changes?");
            if(a==0)
                file_save();
            else if(a==1)
            {
                t.setText("");
                path = "";
                setTitle("VAL Parser - untitled");
                is_saved = true;
                empty_tree();
                ((jsyntaxpane.SyntaxDocument)t.getDocument()).clearUndos();
            }
            else if(a==2) {
            }
        }
    }
    
    public void file_open(){
        if(!is_saved){
            int a = JOptionPane.showConfirmDialog(this, "The text has been changed\nDo you want to save the changes?");
                if(a==0)
                    file_save();
                else if(a==2)
                    return;
        }
        
        JFileChooser fc = new JFileChooser();
        fc.setCurrentDirectory(new File(prefs.get("dirPref",path)));
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Val Files (*.val, *.txt)", "val", "txt");
        fc.addChoosableFileFilter(filter);
        fc.setFileFilter(filter);
        int r=fc.showOpenDialog(this);
        if(r==JFileChooser.CANCEL_OPTION)
            return;
        myfile = fc.getSelectedFile();
        if(myfile == null || myfile.getName().equals(""))
        {
            JOptionPane.showMessageDialog(this, "No file was selected", "Open...", JOptionPane.INFORMATION_MESSAGE);
            return;
        }
        try
        {
            BufferedReader input = new BufferedReader(new FileReader(myfile));
            StringBuilder str = new StringBuilder();
            String line;
            while((line = input.readLine()) != null) // st is declared as string avobe
            str.append(line).append("\n");
            t.setText(str.toString());
            content = t.getText();
            path = myfile.toString();
            is_saved = true;
            prefs.put("dirPref",fc.getCurrentDirectory().toString());
            setTitle("VAL Parser - " + myfile.getName());
            empty_tree();
            output.setText("Output:");
            ((jsyntaxpane.SyntaxDocument)t.getDocument()).clearUndos();
        }
        catch(FileNotFoundException e)
        {
            JOptionPane.showMessageDialog(this, "File not found: \n"+e);
        }
        catch(IOException e)
        {
            JOptionPane.showMessageDialog(this, "File could not be read: \n"+e);
        }
    }

    public void file_save(){
        if(path.equals(""))
        {
            file_save_as();
            return;
        }
        try
        {
            try (FileWriter fw = new FileWriter(path)) {
                fw.write(t.getText());
                content = t.getText();
            }
            setTitle("VAL Parser - " + myfile.getName());
            is_saved = true;
            //System.out.println("File saved");
            //output.append("\n File saved");
        }
        catch(IOException i)
        {
            JOptionPane.showMessageDialog(this,"Failed to save the file","Error",JOptionPane.ERROR_MESSAGE);
        }
    }

    public void file_save_as(){
        JFileChooser fc = new JFileChooser(prefs.get("dirPref",path));
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Val Files (*.val)", "val");
        fc.addChoosableFileFilter(filter);
        fc.setFileFilter(filter);
        int r = fc.showSaveDialog(this);
        if(r==JFileChooser.CANCEL_OPTION)
            return;
        myfile = fc.getSelectedFile();
        if(myfile==null || myfile.getName().equals(""))
        {
            JOptionPane.showMessageDialog(this,"Please enter a file name","Save as...",JOptionPane.INFORMATION_MESSAGE);
            return;
        }

        if(myfile.exists())
        {
            r = JOptionPane.showConfirmDialog(this, "A file with same name already exists.\n Do you want to overwrite?");
            if(r != 0)
                return;
        }
        try
        {
            String extVal = "";
            if (!myfile.toString().endsWith(".val"))
                      extVal = ".val";
            try (FileWriter fw = new FileWriter(myfile + extVal)) {
                myfile = new File(myfile.toString() + extVal);
                fw.write(t.getText());
                content = t.getText();
                path = myfile.toString();
                prefs.put("dirPref",fc.getCurrentDirectory().toString());
                setTitle("VAL Parser - " + myfile.getName());
                is_saved = true;
            }
            
        }
        catch(IOException e)
        {
            JOptionPane.showMessageDialog(this,"Failed to save the file","Error",JOptionPane.ERROR_MESSAGE);
        }
    }

    public void file_exit(){

        if(t.getText().equals("") || t.getText().equals(content))
            System.exit(0);
        else
        {
            int b = JOptionPane.showConfirmDialog(this, "The text has been changed.\nDo you want to save the changes?");

            if(b==0){
                    file_save();
                    if (is_saved)
                    System.exit(0);
            }
            else if(b==1)
                    System.exit(0);
            else if(b==2) {
            }
        }
    }

    /**
     * Undo Compound is provided by jsyntaxpane, the undo and redo buttons simply
     * send key down events Ctrl+Z, Ctrl+Y.
     */
    public void edit_undo() {
            try
            {
                    Robot robot = new Robot();
                    robot.keyPress(KeyEvent.VK_CONTROL);
                    robot.keyPress(KeyEvent.VK_Z);
                    // CTRL+Z is now pressed (receiving application should see a "key down" event.)
                    robot.keyRelease(KeyEvent.VK_Z);
                    robot.keyRelease(KeyEvent.VK_CONTROL);

            } catch (AWTException e) {
                    System.err.println(e);
            }

    }

    public void edit_redo(){
            try
            {
                    Robot robot = new Robot();
                    robot.keyPress(KeyEvent.VK_CONTROL);
                    robot.keyPress(KeyEvent.VK_Y);
                    // CTRL+Y is now pressed (receiving application should see a "key down" event.)
                    robot.keyRelease(KeyEvent.VK_Y);
                    robot.keyRelease(KeyEvent.VK_CONTROL);
            } catch (AWTException e) {
                    System.err.println(e);
            }
    }

    /**
     * Find module is provided by jsyntaxpane, the findo button simply send key
     * down event Ctrl+F.
     */
    
    public void edit_find(){
            try
            {
                    Robot robot = new Robot();
                    robot.keyPress(KeyEvent.VK_CONTROL);
                    robot.keyPress(KeyEvent.VK_F);
                    // CTRL+F is now pressed (receiving application should see a "key down" event.)
                    robot.keyRelease(KeyEvent.VK_F);
                    robot.keyRelease(KeyEvent.VK_CONTROL);

            } catch (AWTException e) {
                    // TODO Auto-generated catch block
                    System.err.println(e);
            }
    }
    
    
    public void edit_toggle_comments(){
            try
            {
                    Robot robot = new Robot();
                    robot.keyPress(KeyEvent.VK_CONTROL);
                    robot.keyPress(KeyEvent.VK_R);
                    // CTRL+R is now pressed (receiving application should see a "key down" event.)
                    robot.keyRelease(KeyEvent.VK_R);
                    robot.keyRelease(KeyEvent.VK_CONTROL);

            } catch (AWTException e) {
                System.err.println(e);
                    // TODO Auto-generated catch block
            }
    }
    /**
     * Clears the workspace jTree setting default values.
     */
    public void empty_tree(){
            DefaultMutableTreeNode root = new DefaultMutableTreeNode("Workspace"); 
            DefaultMutableTreeNode parent;
            DefaultMutableTreeNode child; 
            parent = new DefaultMutableTreeNode("Programs"); 
            root.add(parent);
            child = new DefaultMutableTreeNode("Loaded");
            child.add(new DefaultMutableTreeNode("(Empty)"));
            parent.add(child);
            parent = new DefaultMutableTreeNode("Variables"); 
            root.add(parent);
            parent.add(new DefaultMutableTreeNode("(Empty)"));
            parent = new DefaultMutableTreeNode("Locations"); 
            root.add(parent);
            parent.add(new DefaultMutableTreeNode("(Empty)"));
            jTree.setModel(new javax.swing.tree.DefaultTreeModel(root));
    }
    
    /**
     * Fill_tree functions gets the public static variables from the Val2Parser
     * class. Val2Parser and Val2Lexer SHOULD NOT be modified, they are generated
     * by ANTLRWorks.
     */
    public void fill_tree(){
            TreeSet<String> programs = Val2Parser.setPrograms;
            TreeSet<String> variables = Val2Parser.setVariables;
            TreeSet<String> locations = Val2Parser.setLocations;
            TreeSet<String> loads = Val2Parser.setLoadedPrograms;

            DefaultMutableTreeNode root = new DefaultMutableTreeNode("Workspace"); 
            DefaultMutableTreeNode parent;
            DefaultMutableTreeNode child; 
            
            /**
             * For the parents the iterator extracts variables from the TreeSet 
             * that stores the identifiers from the Parser.
             */
            
            //PROGRAMS
            parent = new DefaultMutableTreeNode("Programs"); 
            root.add(parent);
            Iterator itp=programs.iterator();
            if (!itp.hasNext())
                parent.add(new DefaultMutableTreeNode("(Empty)"));
            while(itp.hasNext())
            {
                parent.add(new DefaultMutableTreeNode((String)itp.next())); 
            }
            //PROGRAMS -> LOADED
            child = new DefaultMutableTreeNode("Loaded");
            Iterator itld=loads.iterator();
            if (!itld.hasNext())
                child.add(new DefaultMutableTreeNode("(Empty)"));
            while(itld.hasNext())
            {
                child.add(new DefaultMutableTreeNode((String)itld.next())); 
            }
            parent.add(child);
            
            //VARIABLES
            parent = new DefaultMutableTreeNode("Variables"); 
            root.add(parent);
            Iterator itv=variables.iterator();
            if (!itv.hasNext())
                parent.add(new DefaultMutableTreeNode("(Empty)"));
            while(itv.hasNext())
            {
                parent.add(new DefaultMutableTreeNode((String)itv.next())); 
            } 

            //LOCATIONS
            parent = new DefaultMutableTreeNode("Locations"); 
            root.add(parent);
            Iterator itl=locations.iterator();
            if (!itl.hasNext())
                parent.add(new DefaultMutableTreeNode("(Empty)"));
            while(itl.hasNext())
            {
                parent.add(new DefaultMutableTreeNode((String)itl.next())); 
            } 
            
            jTree.setModel(new javax.swing.tree.DefaultTreeModel(root));
            for (int i = 0; i < jTree.getRowCount(); i++) {
                jTree.expandRow(i);
            }
            
            //Important to clear TreeSets to avoid repetition of identifiers.
            Val2Parser.setPrograms.clear();
            Val2Parser.setVariables.clear();
            Val2Parser.setLocations.clear();
            Val2Parser.setLoadedPrograms.clear();
            Val2Parser.setLabels.clear();
}
    
    
    public void check_warning(){
        if (!jCheck.isSelected()){
            jWarning.setEnabled(true);
            //System.out.println("it is recommended to clear the memory");
        }
        else if (jSlider.getValue() >= 75){
            jWarning.setEnabled(true);
            //System.out.println("speed may be too high");
        }
        else
            jWarning.setEnabled(false);
        
    }
     
    /**
     * has_errors() checks if the parser generated errors, will be used to
     * determine if output will be generated or not. Omits warnings with
     * simple approach TODO: improve it.
     */
    public boolean has_errors(){
        String out_console = output.getText().replaceAll("line [0-9]*:[0-9]* warning:.*\r?\n?","");
        out_console = out_console.replaceAll("\r?\n","");
        if (out_console.contentEquals("Output:") )
            return false;
        return true;  
    }
            
    
    /**
     * optimize_code() uses java regexp to delete comments, empty lines and add
     * the carriage return to the text file and outputs a txt file, in the same
     * folder of the opened file.
     * @throws IOException 
     */
    public void optimize_code() throws IOException{
        String str, param;
        System.out.println("generating optimized code...");
        str= t.getText().toLowerCase();
        //Remove comments
        str = str.replaceAll(";.*?\r?\n","\r\n");
        
        //Remove empty lines
        str = str.replaceAll("(?m)^[ \t]*\r?\n","");
        
        //Remove white space
        str = str.replaceAll("(\\s+)*\r?\n(\\s+)*","\r\n");
        
        //Add extra new line after each ENDMODULE 'e'
        str = str.replaceAll("\r?\n(\\s+)*e(\\s+)*\r?\n","\r\ne\r\n\r\n");

        //Appends the parameters at the beginning of the code.
        if (jCheck.isSelected())
            param = "zero\r\ny\r\nsp " + jSlider.getValue() + "\r\n\r\n";
        else
            param = "zero\r\nn\r\nsp " + jSlider.getValue() + "\r\n\r\n";
        
        str = param + str + "\r\n";
        try (FileWriter fw = new FileWriter(myfile + "_ok.txt")) {
            fw.write(str);
        }
        System.out.println(myfile + "_ok.txt generated.");
    }
    
    public void run_parser() throws BadLocationException{
        try{
            output.setText("Output:");
            if(t.getText().length()>1){
                file_save();
                if (!is_saved)
                    return;
                ANTLRStringStream cs = new ANTLRStringStream(t.getText(0, t.getDocument().getLength()).toLowerCase());
                Val2Lexer lexer = new Val2Lexer(cs);
                CommonTokenStream tokens = new CommonTokenStream(lexer);
                Val2Parser parser = new Val2Parser(tokens);
                //RuleReturnScope result = parser.compilationUnit();
                parser.rule();
                
                /**
                 * To check if there are no errors simply checks that the
                 * output content is empty. TODO: Change the approach to allow
                 * warnings. DONE x
                 */
                if (!has_errors() & is_saved){
                    System.out.println("\nno errors found.");
                    optimize_code();
                     }
                else if (jCIgnore.isSelected()){
                    System.out.println("\nignoring errors...");
                    optimize_code(); 
                }
                else {
                    int count=0;
                    StringTokenizer stk=new StringTokenizer(output.getText()," ");
                    while(stk.hasMoreTokens()){
                        String token=stk.nextToken();
                        if(token.equals("error:")) count++;
                    }
                    if(count==1)
                        System.out.println("\n"+ count + " error");
                    else
                        System.out.println("\n"+ count + " errors");

                }
                //Actions done with our without errors.
                fill_tree();
            }
                else
                //If 't' is empty.
                    output.setText("Output:\nno code to check.");
        }
        catch(RecognitionException re) {
            System.err.println(re);
        }
        catch(IOException e) {
                    JOptionPane.showMessageDialog(this,"Failed to save the file","Error",JOptionPane.ERROR_MESSAGE);
        }
    }
    
    public void help_about(){
        jAbout.setVisible(true);     
    }
}